<?php

class NCore_FileAction
{
	private $name;
	private $fileName = NULL;
	private $fileContents = NULL;
	private $fileFTPURL;

	public function __construct($name)
	{
		$this->setName($name);
		$this->setFileFTPURL(N::config('file_ftp_url'));
	}
	
	public function setName($name)
	{
		if(!preg_match(N::REGEX_KEY, $name))
		{
			throw new Exception('The name for port port \''.$this->getName().'\' is not valid.  Port names must begin with a letter; contain letters, numbers, or the underscore; and be no longer than 40 characters.');
		}

		$this->name = $name;
	}
	
	public function getName(){ return $this->name; }
	
	public function setFileName($fileName)
	{
		$this->fileName = $this->checkFileName($fileName);
	}
	
	public function getFileName(){return $this->fileName;}
	
	public function setFileContents($fileContents)
	{
		$this->fileContents = $fileContents;
	}
	
	public function getFileContents(){return $this->fileContents;}
	
	public function setFileFTPURL($fileFTPURL)
	{
		$this->fileFTPURL = $fileFTPURL;
	}
	
	public function getFileFTPURL(){return $this->fileFTPURL;}
	
	public function delete($path = NULL)
	{
        if (!is_null($path))
        {
            $this->setFileName($path);
        }

		if(is_null($this->getFileFTPURL()))
		{
			unlink($this->getFileName());			
		}
		else
		{					
			// try curl
			$this->deleteWithCURL();
		}
	}
	
	public function save($path = NULL, $fileContents = NULL)
	{
        if (!is_null($path))
        {
            $this->setFileName($path);
        }

        if (!is_null($fileContents))
        {
            $this->setFileContents($fileContents);
        }

		if(is_null($this->getFileFTPURL()))
		{
			$handle = @fopen($this->getFileName(), 'w');
			
			if(!$handle === FALSE)
			{
				fwrite($handle, $this->getFileContents());	
				fclose($handle);
				return;
			}
		}
		else
		{			
			// try curl
			$this->saveWithCURL();
		}
	}
	
	protected function saveWithCURL()
	{
		$this->checkFileNameContentsFTPURL4Nulls();
	
		$temp = tmpfile();
		$tempSize = fwrite($temp, $this->getFileContents());
        rewind($temp);
		
		$filename = $this->getFileFTPURL().$this->getFileName();
		
		$ch = curl_init();
		
		curl_setopt($ch, CURLOPT_URL, $filename);
		curl_setopt($ch, CURLOPT_UPLOAD, 1);
		curl_setopt($ch, CURLOPT_INFILE, $temp);
		curl_setopt($ch, CURLOPT_INFILESIZE, $tempSize);
		// needed so output isn't echo'd back
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        
		curl_exec($ch);
		$error_no = curl_errno($ch);
		curl_close ($ch);
		if($error_no != 0) {
			if(is_int($error_no))
			{
				throw new Exception('There was an error saving the file \''.$filename.'\'. CURL error number:'.$error_no);
			}
			else
			{
				throw new Exception('There was an error saving the file \''.$filename.'\', and the CURL error number was invalid, too.');
			}
		}
		
		fclose($temp); // this removes the temp file		
	}
	
	protected function deleteWithCURL()
	{
		$this->checkFileNameFTPURL4Nulls();
		
		$ch = curl_init();
		
		curl_setopt($ch, CURLOPT_URL, $this->getFileFTPURL());
		// needed so output isn't echo'd back
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_QUOTE, array("DELE ".$this->getFileName()));
		$result = curl_exec($ch);
		$error_no = curl_errno($ch);
		curl_close ($ch);
		
		if($error_no != 0) {
			if(is_int($error_no))
			{
				throw new Exception('There was an error deleting the file \''.$this->getFileName().'\'. CURL error number:'.$error_no);
			}
			else
			{
				throw new Exception('There was an error deleting the file \''.$this->getFileName().'\', and the CURL error number was invalid, too.');
			}
		}	
	}
	
	protected function checkFileNameContentsFTPURL4Nulls()
	{
		if(is_null($this->getFileName()))
		{
			throw new Exception('The file action \''.$this->getName().'\' has a null value set for fileName.');
		}	
		
		if(is_null($this->getFileContents()))
		{
			throw new Exception('The file action \''.$this->getName().'\' has a null value set for fileContents.');
		}	
		
		if(is_null($this->getFileFTPURL()))
		{
			throw new Exception('The file action \''.$this->getName().'\' has a null value set for fileFTPURL, which can be set in nconfig or directly on this object.');
		}	
	}
	
	protected function checkFileNameFTPURL4Nulls()
	{
		if(is_null($this->getFileName()))
		{
			throw new Exception('The file action \''.$this->getName().'\' has a null value set for fileName.');
		}	
		
		if(is_null($this->getFileFTPURL()))
		{
			throw new Exception('The file action \''.$this->getName().'\' has a null value set for fileFTPURL, which can be set in nconfig or directly on this object.');
		}	
	}
	
	protected function checkFileName($fileName)
	{
		if(substr(trim($fileName), 0, 1) != '/')
		{
			throw new Exception('The save() method of the file action \''.$this->getName().'\' expects a path syntax, for example \'/filename.jpeg\' or \'/home/username/public_html/uploads/filename.jpeg\'.');
		}
		else
		{
			return $fileName;
		}		
	}
		
	function __call($method, $args)
	{
		if($this->isWither($method))
		{
			$method = $this->removePrefix($method, 4);
			call_user_func_array(array($this, 'set'.$method), $args);
			return $this;
		}
		else
		{
			throw new Exception('There is no method called \''.$method.'\'().');
		}
	}
	protected function isWither($string)
	{
		$wither = false;
		
		$methodPrefix = substr($string, 0, 4);
		
		if($methodPrefix == "with")
		{
			$wither = true;
		}

		return $wither;
	}
	protected function removePrefix($string, $num = 3)
	{
		return substr($string, $num);
	}
}

?>